//
// Created by tang on 3/6/23.
//

#ifndef PIINFO_SVC_MANAGER_HPP
#define PIINFO_SVC_MANAGER_HPP

#include "sdk_config.h"

#include <type_traits>

enum class service_type {
    http = 0,
    config,
    timer,
    render,

    count,
};

class PI_API IService {
public:
    virtual ~IService();

    virtual service_type get_type() const = 0;
};

template <service_type tag>
class TaggedService: public IService {
public:
    static constexpr service_type service_tag = tag;

    service_type get_type() const final {
        return service_tag;
    }
};

template<typename T>
concept tagged_service = std::is_base_of_v<IService, T> && std::is_same_v<std::decay_t<decltype (T::service_tag)>, service_type>;

class ServiceManager {
    ServiceManager();
    ~ServiceManager();

public:
    PI_API
    static ServiceManager* instance();

    PI_API
    void clear();

    PI_API
    ServiceManager* register_service(IService *svc);

    PI_API
    IService* request_service(service_type type);

    template<tagged_service TService>
    PI_INLINE TService *request_service() {
        return dynamic_cast<TService*>(request_service (TService::service_tag));
    }
};

#endif  // PIINFO_SVC_MANAGER_HPP
